package cn.mickey.exchange.service;

import cn.hutool.core.bean.BeanUtil;
import cn.mickey.exchange.domain.model.IdleItemModel;
import cn.mickey.exchange.domain.model.OrderModel;
import cn.mickey.exchange.mapper.IdleItemMapper;
import cn.mickey.exchange.mapper.OrderMapper;
import cn.mickey.exchange.task.OrderTask;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 订单的增删改查
 * 订单表
 * user_id建索引
 * idle_id建索引
 * @author mickey
 */
@Service
public class OrderService extends ServiceImpl<OrderMapper, OrderModel> {

    @Resource
    private IdleItemMapper idleItemMapper;


    private static HashMap<Integer, ReentrantLock> lockMap = new HashMap<>();

    static {
        for (int i = 0; i < 100; i++) {
            lockMap.put(i, new ReentrantLock(true));
        }
    }

    /**
     * 获取订单信息，同时获取对应的闲置信息
     *
     * @param orderId
     * @return
     */
    public OrderModel getOrder(Long orderId) {
        OrderModel orderModel = baseMapper.selectOne(new LambdaQueryWrapper<OrderModel>()
                .eq(OrderModel::getOrderId, orderId));
        orderModel.setIdleItem(idleItemMapper.getIdleItemById(orderModel.getIdleId()));
        return orderModel;
    }

    /**
     * 新增订单，同时下架闲置
     * 用了事务串行化，后续要优化，修改更新的sql，增加更新条件，而不是在代码中判断条件
     * 业务逻辑可优化，改为支付时才下架。
     * 新功能待做，需要新增订单超时处理
     * （订单超时：
     * 1、重新上架闲置；2、修改订单状态；
     * 3、确保订单取消前不会影响用户的支付，支付前要判断订单状态并加读锁，取消订单时要判断订单状态为未支付才能取消；
     * 4、保证延期任务一定执行，即确保任务不会因为系统异常而消失）
     *
     * @param orderModel
     * @return
     */
    public boolean addOrder(OrderModel orderModel) {
        IdleItemModel idleItemModel = idleItemMapper.getIdleItemById(orderModel.getIdleId());
        if (idleItemModel.getIdleStatus() != 1) {
            return false;
        }
        IdleItemModel idleItem = new IdleItemModel();
        idleItem.setIdleId(orderModel.getIdleId())
                .setUserId(idleItemModel.getUserId())
                .setIdleStatus((byte) 2);
        int key = (int) (orderModel.getIdleId() % 100);
        ReentrantLock lock = lockMap.get(key);
        boolean flag;
        try {
            lock.lock();
            flag = addOrderHelp(idleItem, orderModel);
        } finally {
            lock.unlock();
        }
        return flag;
    }

    /**
     * 帮助添加订单
     *
     * @param idleItem
     * @param orderModel
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrderHelp(IdleItemModel idleItem, OrderModel orderModel) {
        IdleItemModel idleItemModel = idleItemMapper.getIdleItemById(orderModel.getIdleId());
        if (idleItemModel.getIdleStatus() != 1) {
            return false;
        }
        IdleItemModel newIdle = new IdleItemModel();
        BeanUtil.copyProperties(idleItem,newIdle);
       /* newIdle.setIdleName(idleItem.getIdleName())
                .setIdleDetails(idleItem.getIdleDetails())
                .setPictureList(idleItem.getPictureList())
                .setIdlePlace(idleItem.getIdlePlace())
                .setIdlePlace(idleItem.getIdlePlace())
                .setIdleLabel(idleItem.getIdleLabel())
                .setReleaseTime(idleItem.getReleaseTime())
                .setIdleStatus(idleItem.getIdleStatus());*/
        if (idleItemMapper.update(newIdle, new LambdaUpdateWrapper<IdleItemModel>()
                .eq(IdleItemModel::getIdleId, idleItem.getIdleId())) == 1) {
            if (baseMapper.insert(orderModel) == 1) {
                orderModel.setOrderStatus((byte) 4);
                //半小时未支付则取消订单
                OrderTaskService.addOrderTask(new OrderTask(orderModel, 30 * 60));
                return true;
            } else {
                throw new RuntimeException();
            }
        }
        return false;
    }

    /**
     * 更新订单状态，无验证，后期修改为定制的更新sql
     * 后期改为在支付时下架闲置
     *
     * @param orderModel
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrder(OrderModel orderModel) {
        //不可修改的信息
        orderModel.setOrderNumber(null)
                .setUserId(null)
                .setIdleId(null)
                .setCreateTime(null);
        if (orderModel.getOrderStatus() == 4) {
            //取消订单,需要优化，减少数据库查询次数
            OrderModel order = getOrder(orderModel.getOrderId());
            if (order.getOrderStatus() != 0) {
                return false;
            }
            IdleItemModel idleItemModel = idleItemMapper.getIdleItemById(order.getIdleId());
            if (idleItemModel.getIdleStatus() == 2) {
                IdleItemModel idleItem = new IdleItemModel();
                idleItem.setIdleId(order.getIdleId())
                        .setUserId(idleItemModel.getUserId())
                        .setIdleStatus((byte) 1);
                if (baseMapper.updateByPrimaryKeySelective(orderModel) == 1) {
                    if (idleItemMapper.updateByPrimaryKeySelective(idleItem) == 1) {
                        return true;
                    } else {
                        throw new RuntimeException();
                    }
                }
                return false;
            } else {
                if (baseMapper.updateByPrimaryKeySelective(orderModel) == 1) {
                    return true;
                } else {
                    throw new RuntimeException();
                }
            }
        }

        return baseMapper.updateByPrimaryKeySelective(orderModel) == 1;
    }

    /**
     * 获取用户所有订单信息
     */
    public Page getAllOrder(int p, int n) {
        return baseMapper.selectPage(new Page(p, n), new LambdaQueryWrapper<OrderModel>()
                .orderByDesc(OrderModel::getCreateTime));
    }

    /**
     * 获取我的所有订单
     * 同时查询出对应的闲置信息
     * 未做分页
     * userId建索引
     *
     * @param userId
     * @return
     */
    public List<OrderModel> getMyOrder(Long userId) {
        List<OrderModel> orderList = baseMapper.selectList(new LambdaQueryWrapper<OrderModel>()
                .eq(OrderModel::getUserId, userId)
                .orderByDesc(OrderModel::getCreateTime));
        for (OrderModel orderModel : orderList) {
            orderModel.setIdleItem(idleItemMapper.getIdleItemById(orderModel.getIdleId()));
        }
        return orderList;
    }

    /**
     * 查询用户卖出的闲置
     *
     * @param userId
     * @return
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public List<OrderModel> getMySoldIdle(Long userId) {
        List<IdleItemModel> idleItemList = idleItemMapper
                .selectList(new LambdaQueryWrapper<IdleItemModel>()
                        .ne(IdleItemModel::getIdleStatus, 1)
                        .eq(IdleItemModel::getUserId, userId));
        List<OrderModel> orderList = new ArrayList<>();
        if (idleItemList.size() > 0) {
            for (IdleItemModel idleItemModel : idleItemList) {
                OrderModel orderModel = baseMapper.selectOne(new LambdaQueryWrapper<OrderModel>()
                        .eq(OrderModel::getIdleId, idleItemModel.getIdleId())
                        .eq(OrderModel::getOrderStatus,1));
                if (orderModel != null) {
                    orderModel.setIdleItem(idleItemModel);
                    orderList.add(orderModel);
                }
            }
        }
        return orderList;
    }

    public boolean deleteOrder(Long id) {
        return baseMapper.update(null, new LambdaUpdateWrapper<OrderModel>()
                .set(OrderModel::getIsDeleted, 1).eq(OrderModel::getOrderId, id)) == 1;
    }
}
